/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.projeto.persistence.jpa;

import br.com.projeto.persistence.exception.JPADeleteException;
import br.com.projeto.persistence.exception.JPAInsertException;
import br.com.projeto.persistence.exception.JPAQueryException;
import br.com.projeto.persistence.exception.JPAUpdateException;
import br.com.projeto.persitence.util.Constantes;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TemporalType;

/**
 *
 * @author matheus
 */
public class DaoGenericImpl<T> implements DaoGeneric<T> {

        /**
         * Servico central para todas as acoes de persistencia.
         */
        /**
         * Metodo responsavel por persistir objetos.
         * @param entidadeGenerica Entidade a ser incluida.
         * @throws JPAInsertException Se houver erro no acesso a base de dados.
         */
        public T save(T entidadeGenerica) throws JPAInsertException {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        manager.persist(entidadeGenerica);
                        manager.getTransaction().commit();
                        manager.refresh(entidadeGenerica);
                } catch (Exception ex) {
                        ex.printStackTrace();
                        utility.rollbackTransaction(manager);
                        throw new JPAInsertException(Constantes.MSG_ERRO_INSERCAO, ex);
                }
                return entidadeGenerica;
        }

        /**
         * Metodo responsavel por excluir objetos.
         * @param entidadeGenerica A entidade a ser excluida.
         * @throws JPADeleteException Se houver erro no acesso a base de dados.
         */
        public void delete(Object entidadeGenerica) throws JPADeleteException {
                Object id = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        id = manager.merge(entidadeGenerica);
                        manager.remove(id);
                        utility.commitTransaction(manager);
                } catch (Exception ex) {
                        ex.printStackTrace();
                        utility.rollbackTransaction(manager);
                        throw new JPADeleteException(Constantes.MSG_ERRO_REMOCAO, ex);
                }
        }

        /**
         * Metodo responsavel por alterar objetos.
         * @param entidadeGenerica A entidade a ser atualizada.
         * @throws JPAUpdateException Se houver erro no acesso a base de dados.
         */
        public Object update(Object entidadeGenerica) throws JPAUpdateException {
                Object object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        object = manager.merge(entidadeGenerica);
                        utility.commitTransaction(manager);
                } catch (Exception ex) {
                        throw new JPAUpdateException(Constantes.MSG_ERRO_ATUALIZACAO, ex);
                }
                return object;
        }

        /**
         * Metodo responsavel por alterar objetos.
         * @param entidadeGenerica A entidade a ser atualizada.
         * @throws JPAUpdateException Se houver erro no acesso a base de dados.
         */
        public void updateTransaction(Object entidadeGenerica1, Object entidadeGenerica2) throws JPAUpdateException {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        manager.merge(entidadeGenerica1);
                        manager.merge(entidadeGenerica2);
                        utility.commitTransaction(manager);
                } catch (Exception ex) {
                        ex.printStackTrace();
                        utility.rollbackTransaction(manager);
                        throw new JPAUpdateException(Constantes.MSG_ERRO_ATUALIZACAO, ex);
                }
        }

        /**
         * Metodo para recuperar um Objeto a partir de uma chave primaria.
         * @param clazz A classe da entidade.
         * @param chave A chave primaria da entidade.
         * @return A entidade recupera ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public T getObjectChave(Class<? extends T> clazz, long chave) throws JPAQueryException {
                T retorno = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        retorno = (T) manager.find(clazz, chave);
                        utility.commitTransaction(manager);
                } catch (Exception ex) {
                        ex.printStackTrace();
                        manager.getTransaction().rollback();
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, ex);
                }
                return retorno;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param entidadeGenerica O campo do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public List<T> listObject(String campo, String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param entidadeGenerica O campo do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public List<T> listObject(long campo, String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        public List<T> listObjectAll(String campo1, String campo2, String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor1", campo1);
                        query.setParameter("valor2", campo2);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param matricula A matricula do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public List<T> listObjects(String campo1, long campo2, String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor1", campo1);
                        query.setParameter("valor2", campo2);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param matricula A matricula do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public T object(String campo, String consulta) throws JPAQueryException {
                T object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        e.printStackTrace();
                        return null;
                }
                return object;
        }

        public T object(int campo, String consulta) throws JPAQueryException {
                T object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        e.printStackTrace();
                        return null;
                }
                return object;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param matricula A matricula do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public T object(long campo, String consulta) throws JPAQueryException {
                T object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return object;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param matricula A matricula do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public T object(String campo1, String campo2, String consulta) throws JPAQueryException {
                T object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor1", campo1);
                        query.setParameter("valor2", campo2);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return object;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param matricula A matricula do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public T object(String campo1, long campo2, String consulta) throws JPAQueryException {
                T object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor1", campo1);
                        query.setParameter("valor2", campo2);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return object;
        }

        /**
         * Metodo para recuperar um Objeto de uma entidade.
         * @param matricula A matricula do objeto a ser recuperado.
         * @param consulta A consulta pelo objeto a ser recuperado.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public T object(String campo1, String campo2, String campo3, String consulta) throws JPAQueryException {
                T object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor1", campo1);
                        query.setParameter("valor2", campo2);
                        query.setParameter("valor3", campo3);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return object;
        }

        /**
         * Metodo para validar Objetos de uma entidade.
         * @param nome O nome do objeto a ser validado.
         * @param senha A senha do objeto a ser validada.
         * @param consulta A consulta pelos objetos a serem recuperados e validados.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public List<T> listObjectByData(Date data, String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", data, TemporalType.DATE);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        public T listObjectByEnum(Enum campo, String consulta) throws JPAQueryException {
                T objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                objects = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        /**
         * Metodo para validar Objetos de uma entidade.
         * @param nome O nome do objeto a ser validado.
         * @param senha A senha do objeto a ser validada.
         * @param consulta A consulta pelos objetos a serem recuperados e validados.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public List<T> listObjectByEnum(long campo, Enum campo2, String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        query.setParameter("valor2", campo2);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        /**
         * Metodo para listar Objetos de uma entidade.
         * @param consulta A consulta pelos objetos a serem recuperados.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public List<T> listObjects(String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        /**
         * Metodo para validar Objetos de uma entidade.
         * @param nome O nome do objeto a ser validado.
         * @param senha A senha do objeto a ser validada.
         * @param consulta A consulta pelos objetos a serem recuperados e validados.
         * @return A entidade recuperada ou Null se a mesma nao existir.
         * @throws JPAQueryException Se houver erro no acesso a base de dados.
         */
        public List<T> listDataBetween(Date dataInicio, Date dataFim, String consulta) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor1", dataInicio, TemporalType.DATE);
                        query.setParameter("valor2", dataFim, TemporalType.DATE);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        public List<T> listDataBetweenLimit(Date dataInicio, Date dataFim, String consulta, int totalLinhas) throws JPAQueryException {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta).setMaxResults(totalLinhas);
                        query.setParameter("valor1", dataInicio, TemporalType.DATE);
                        query.setParameter("valor2", dataFim, TemporalType.DATE);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return objects;
        }

        public T validarCampos(String campo1, String campo2, String consulta) throws JPAQueryException {
                T object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor1", campo1);
                        query.setParameter("valor2", campo2);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                        if (object == null) {
                                return null;
                        }
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
                return object;
        }

        /**
         * Metodo que retorna uma lista de objetos de um determinado dia de uma entidade especifica.
         * @param id
         * @param dia
         * @param consulta
         * @return
         *	List<T>
         */
        public List<T> getObjectByEntityOfDay(long id, Calendar diaI, Calendar diaF, String consulta) {
                List<T> listObject = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", id);
                        query.setParameter("dataI", diaI, TemporalType.TIMESTAMP);
                        query.setParameter("dataF", diaF, TemporalType.TIMESTAMP);
                        listObject = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return listObject;
        }


        /* ############################################################################################*/
        /**
         * Metodo responsavel por retornar uma lista de objetos passando um campo como parametro
         * @param entidadeGenerica
         * @param consulta
         * @return
         */
        public List<T> getListObjectByParameter(Object campo, String consulta) {
                List<T> lista = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        lista = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return lista;
        }

        /**
         * Metodo uma lista de objetos passando apenas uma consulta
         * @param consulta
         * @return
         */
        public List<T> getObjects(String consulta) {
                List<T> object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        object = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return object;
        }

        /**
         * Metodo um objeto especifico passando um campo como parametro
         * @param entidadeGenerica
         * @param consulta
         * @return
         */
        public Object getObject(Object campo, String consulta) {
                Object object = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                object = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return object;
        }

        /**
         * Metodo que busca os objetos em um determinado dia
         * @param consulta
         * @param dataAtual - inicio do periodo
         * @return
         *	Retorna uma lista de objetos.
         */
        public List<T> getObjectsDataAtual(String consulta, Calendar dataAtual) {
                List<T> listObjects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("dataAtual", dataAtual, TemporalType.TIMESTAMP);
                        listObjects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return listObjects;
        }

        /**
         * Metodo que busca os objetos em um determinado periodo
         * @param consulta
         * @param dataInicio - inicio do periodo
         * @param dataFim - fim do periodo
         * @return
         *	Retorna uma lista de objetos.
         */
        public List<T> getObjectsByData(String consulta, Calendar dataInicio, Calendar dataFim) {
                List<T> listObjects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("dataI", dataInicio);
                        query.setParameter("dataF", dataFim);
                        listObjects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return listObjects;
        }

        /**
         * Metodo para remover uma lista de objetos
         * @param objList
         */
        public void removeList(List<T> objList) {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        manager.getTransaction().begin();
                        for (Object elem : objList) {
                                delete(elem);
                        }
                        manager.getTransaction().commit();
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
        }

        public List<T> getObjetcsByData(Calendar data, String consulta) {
                List<T> result = new ArrayList<T>();
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", data);
                        result = (List<T>) query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception ex) {
                        ex.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return result;
        }

        /**
         * Metodo responsavel por buscar uma lista de objetos passando dois parametros.
         * @param objeto1
         * @param objeto2
         * @param consulta
         * @return
         */
        public List<T> listObjectsByParameter(Date data, int dia, String consulta) {
                List<T> listObjects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", data, TemporalType.DATE);
                        query.setParameter("valor2", dia);
                        listObjects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return listObjects;
        }

        public List<T> getObjectsWithLimite(String consulta, int limite) {
                List<T> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta).setMaxResults(limite);
                        objects = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                } finally {
                        return objects;
                }
        }

        public Object getObject(Object valor1, Object valor2, String consulta) {
                Object retorno = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", valor1);
                        query.setParameter("valor2", valor2);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                retorno = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                        return retorno;
                } catch (Exception ex) {
                        Logger.getLogger(DaoGeneric.class.getName()).log(Level.SEVERE, null, ex);
                        utility.rollbackTransaction(manager);
                        return null;
                }
        }

        public Object getObject(String consulta) {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        Object retorno = null;
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                retorno = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                        return retorno;
                } catch (Exception ex) {
                        Logger.getLogger(DaoGeneric.class.getName()).log(Level.SEVERE, null, ex);
                        utility.rollbackTransaction(manager);
                        return null;
                }
        }

        /**
         * M�todo que retorna a quantidade de registros � partir de uma determinada NamedQuery
         * @param namedQuery NamedQuery utilizada
         * @return retorna a quantidade de registros de um determinado objeto na base de dados<br/>
         *         retorna <b>-1</b> se ouver algum erro na execu��o do m�todo
         */
        public long getTotalRegistros(String namedQuery) {
                long resultado = 0;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(namedQuery);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                resultado = (Long) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception ex) {
                        Logger.getLogger(DaoGeneric.class.getName()).log(Level.SEVERE, null, ex);
                        utility.rollbackTransaction(manager);
                        return -1;
                }

                return resultado;
        }

        public T getTotal(String consulta) {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        T retorno = null;
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                retorno = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);

                        return retorno;
                } catch (Exception ex) {
                        Logger.getLogger(DaoGeneric.class.getName()).log(Level.SEVERE, null, ex);
                        utility.rollbackTransaction(manager);
                        return null;
                }
        }

        public T getObjectsWithLimite(String consulta) {
                T objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNamedQuery(consulta).setMaxResults(1);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                objects = (T) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                } finally {
                        return objects;
                }
        }

        public T[] getObjectsByDataNative(String consulta, Date dataInicio, Date dataFim) {
                T[] valores = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNativeQuery(consulta);
                        query.setParameter("dataI", dataInicio);
                        query.setParameter("dataF", dataFim);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                valores = (T[]) query.getSingleResult();
                        }
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return valores;
        }

        public List<String> listObjects(long campo, String consulta) throws JPAQueryException {
                List<String> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        objects = query.getResultList();
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(e.getMessage(), e);
                }
                return objects;
        }

        public List<String> listObjects(String campo, String consulta) throws JPAQueryException {
                List<String> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query query = manager.createNamedQuery(consulta);
                        query.setParameter("valor", campo);
                        objects = query.getResultList();
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(e.getMessage(), e);
                }
                return objects;
        }

        public T getObjectByDataNative(long campo, String consulta) {
                T valor = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query query = manager.createNativeQuery(consulta);
                        query.setParameter("valor", campo);
                        List<T> result = (List<T>) query.getResultList();
                        if (result.size() > 0) {
                                valor = (T) query.getSingleResult();
                        }
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        e.printStackTrace();
                }
                return valor;
        }

        public boolean insertDataNative(String consulta) {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        manager.createNativeQuery(consulta).executeUpdate();
                        utility.commitTransaction(manager);
                        return true;

                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        e.printStackTrace();
                }
                return false;
        }

        public List<String> listObjectString(String consulta) throws JPAQueryException {
                List<String> objects = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query query = manager.createNamedQuery(consulta);
                        objects = query.getResultList();
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        e.printStackTrace();
                }
                return objects;
        }

        public Object getObjectsByNativeQuery(String consulta) {
                Object valores = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNativeQuery(consulta);
                        valores = query.getResultList().toArray();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return valores;
        }

        public List<Object[]> getObjectosConsultaNativa(String consulta) {
                List<Object[]> objetos = null;
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        utility.beginTransaction(manager);
                        Query query = manager.createNativeQuery(consulta);
                        objetos = query.getResultList();
                        utility.commitTransaction(manager);
                } catch (Exception e) {
                        e.printStackTrace();
                        utility.rollbackTransaction(manager);
                }
                return objetos;
        }

        public Object pesquisaObjetoPorParametro(Map<String, Object> params, String query) throws JPAQueryException {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query q = manager.createNamedQuery(query);
                        if (!params.isEmpty()) {
                                for (String chave : params.keySet()) {
                                        q.setParameter(chave, params.get(chave));
                                }
                        }
                        return q.getSingleResult();
                } catch (NoResultException nre) {
                        return null;
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
        }

        public T pesquisaPorParametro(Map<String, Object> params, String query) throws JPAQueryException {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query q = manager.createNamedQuery(query);
                        if (!params.isEmpty()) {
                                for (String chave : params.keySet()) {
                                        q.setParameter(chave, params.get(chave));
                                }
                        }
                        return (T) q.getSingleResult();
                } catch (NoResultException nre) {
                        return null;
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
        }

        public List<T> listarPesquisaPorParametro(Map<String, Object> params, String query) throws JPAQueryException {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query q = manager.createNamedQuery(query);
                        if (!params.isEmpty()) {
                                for (String chave : params.keySet()) {
                                        q.setParameter(chave, params.get(chave));
                                }
                        }
                        return q.getResultList();
                } catch (NoResultException nre) {
                        return null;
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
        }

        public List<Object> listarObjetosPorParametro(Map<String, Object> params, String query) throws JPAQueryException {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query q = manager.createNamedQuery(query);
                        if (!params.isEmpty()) {
                                for (String chave : params.keySet()) {
                                        q.setParameter(chave, params.get(chave));
                                }
                        }
                        return q.getResultList();
                } catch (NoResultException nre) {
                        return null;
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
        }

        /**
         * Método de consulta genérico, podendo retornar uma lista de qualquer objeto.
         * Desse modo, faz-se necessário o uso de cast no objeto de retorno para o tipo esperado.
         * Ex: Em uma consulta que provavelmente retornará uma lista de Strings, usa-se (List<String>)
         *     Caso o resultado esperado seja uma lista de um outro objeto, usa-se (List<NomeDaClasse>)
         */
        public Object listarPesquisaPorParametros(Map<String, Object> params, String query) throws JPAQueryException {
                EntityManager manager = null;
                JPAUtility utility = new JPAUtility();
                try {
                        manager = utility.getEntityManager();
                        Query q = manager.createNamedQuery(query);
                        if (!params.isEmpty()) {
                                for (String chave : params.keySet()) {
                                        q.setParameter(chave, params.get(chave));
                                }
                        }
                        return q.getResultList();
                } catch (Exception e) {
                        utility.rollbackTransaction(manager);
                        throw new JPAQueryException(Constantes.MSG_ERRO_CONSULTA, e);
                }
        }
}
